/**
 * 1 获取当前定位城市
 * 2 使用地址解析器解析当前城市坐标
 * 3 调用centerAndZoom() 方法在地图中展示当前城市,并设置缩放级别为11
 * 4 在地图中展示该城市,并添加比例尺和平移缩放控件
 *
 */
/**
 * 1 获取房源数据
 * 2 遍历数据,创建覆盖物,给每个覆盖物添加唯一标识(后面要用)
 * 3 给覆盖物添加单击事件
 * 4 在单击事件中,获取到当前点击项的唯一标识
 * 5 放大地图(级别为13),调用clearOverlays() 方法清除当前覆盖物
 */

import React from "react";

import { API } from "../../utils/api";
import styles from "./index.module.css";
import { Link } from "react-router-dom";
import { Toast } from "antd-mobile";
import NavHeader from "../../components/NavHeader";
// 导入 BASE_URL
import { BASE_URL } from "../../utils/url";
// 导入 HouseItem 组件
import HouseItem from "../../components/HouseItem";
// 覆盖物样式
const labelStyle = {
  cursor: "pointer",
  border: "0px solid rgb(255,0,0)",
  padding: "0px",
  whiteSpace: "nowrap",
  fontSize: "12px",
  color: "rgb(255,255,255)",
  textAlign: "center",
};

export default class Map extends React.Component {
  state = {
    // 小区下的房源列表
    housesList: [],
    // 表示是否展示房源列表
    isShowList: false,
  };

  componentDidMount() {
    this.initMap();
  }

  // 初始化地图
  initMap() {
    // 获取当前定位城市
    const { label, value } = JSON.parse(localStorage.getItem("hkzf_city"));
    // 初始化地图实例
    // 注意：在 react 脚手架中全局对象需要使用 window 来访问，否则，会造成 ESLint 校验错误
    const map = new window.BMapGL.Map("container");
    // 在别的方法中能使用 map 对象
    this.map = map;
    // 创建地址解析器实例
    var myGeo = new window.BMapGL.Geocoder();
    // 将地址解析结果显示在地图上，并调整地图视野
    myGeo.getPoint(
      label,
      async (point) => {
        if (point) {
          //  初始化地图
          map.centerAndZoom(point, 11);
          // 添加控件 平移缩放 比例尺
          map.addControl(new window.BMapGL.NavigationControl());
          map.addControl(new window.BMapGL.ScaleControl());
          this.renderOverlays(value);
        }
      },
      label
    );
  }

  // 渲染覆盖物入口
  // 1 接受区域 id 参数,获取该区域下的房源数据
  // 2 获取房源类型以及下级地图缩放级别
  async renderOverlays(id) {
    // 开启 loading
    try {
      Toast.loading("数据加载中", 0, null, false);
      const res = await API.get(`/area/map?id=${id}`);
      Toast.hide();
      const data = res.data.body;
      // 调用 getTypeAndZoom 方法获取级别和类型
      const { nextZoom, type } = this.getTypeAndZoom();
      data.forEach((item) => {
        // 创建覆盖物
        this.createOverlays(item, nextZoom, type);
      });
    } catch (e) {
      Toast.hide();
    }
  }

  //计算要绘制的覆盖物类型和下一个缩放级别
  // 区 -> 11, 范围: 10-12
  // 镇 -> 13, 范围: 12-14
  // 小区 -> 15, 范围: 14-15
  getTypeAndZoom() {
    const zoom = this.map.getZoom();
    let nextZoom, type;
    if (zoom >= 10 && zoom < 12) {
      // 区
      // 下一级缩放级别
      nextZoom = 13;
      // circle 表示圆形覆盖物(区、振镇)
      type = "circle";
    } else if (zoom >= 12 && zoom < 14) {
      // 镇
      nextZoom = 15;
      type = "circle";
    } else if (zoom >= 14 && zoom < 16) {
      // 小区
      type = "rect";
    }
    return { nextZoom, type };
  }

  // 创建覆盖物
  createOverlays(data, nextZoom, type) {
    const {
      coord: { longitude, latitude },
      label: areaName,
      count,
      value,
    } = data;

    // 创建坐标对象  longitude 经度 latitude 纬度
    const areaPoint = new window.BMapGL.Point(longitude, latitude);

    if (type === "rect") {
      // 小区
      this.createRect(areaPoint, areaName, count, value);
    } else {
      // 区和镇
      this.createCircle(areaPoint, areaName, count, value, nextZoom);
    }
  }

  // 创建区、镇覆盖物
  createCircle(areaPoint, areaName, count, value, nextZoom) {
    const opts = {
      position: areaPoint,
      offset: new window.BMapGL.Size(-35, -35),
    };
    // 创建文本覆盖物
    const label = new window.BMapGL.Label("", opts);
    // 给label 设置唯一标识
    label.id = value;
    // 设置房源覆盖物的内容
    label.setContent(`
      <div class="${styles.bubble}">
        <p class="${styles.name}">${areaName}</p>
        <p > ${count}套</p>
      </div>
    `);

    // 设置样式
    label.setStyle(labelStyle);
    // 添加单击事件
    label.addEventListener("click", (e) => {
      // 获取当前点击区域下的房源数据
      this.renderOverlays(value);
      // 放大地图,以当前点击的覆盖物为中心放大地图
      // 第一个参数,坐标对象
      // 第二个参数,放大级别
      this.map.centerAndZoom(areaPoint, nextZoom);
      // 清除覆盖物信息
      this.map.clearOverlays();
    });

    this.map.addOverlay(label);
  }

  // 创建小区覆盖物
  createRect(areaPoint, areaName, count, value) {
    /**
     *  1 创建 Label、设置样式、设置HTML内容，绑定表单事件
     *  2 在点击事件中，获取该小区的房源数据
     *  3 展示房源列表
     *  4 渲染获取到的房源列表
     *  5 调用地图 panBy()方法，移动地图到中间位置
     *  6 监听地图 movestart 事件，在移动地图时隐藏房源列表
     */
    const opts = {
      position: areaPoint,
      offset: new window.BMapGL.Size(-50, -28),
    };
    // 创建文本覆盖物
    const label = new window.BMapGL.Label("", opts);
    // 给label 设置唯一标识
    label.id = value;
    // 设置房源覆盖物的内容
    label.setContent(`
      <div class="${styles.rect}">
        <span class="${styles.housename}">${areaName}</span>
        <span class="${styles.housenum}">${count}</span>
        <i class="${styles.arrow}"></i>
      </div>
    `);

    // 设置样式
    label.setStyle(labelStyle);
    // 添加单击事件
    label.addEventListener("click", (e) => {
      this.getHousesList(value);
      /**
       * 调用地图 panBy() 方法,移动地图到中心位置
       * 公式:  垂直位移:(window.innerHeight - 330) / 2 -target.clientY
       *        水平位移:window.innerWidth / 2 - target.clientX
       * e.domEvent.changedTouches[0].clientX    e.domEvent.changedTouches[0].clientY
       */
      this.map.panBy(
        window.innerWidth / 2 - e.domEvent.changedTouches[0].clientX,
        (window.innerHeight - 330) / 2 - e.domEvent.changedTouches[0].clientY
      );
    });
    // 添加移动事件
    this.map.addEventListener("movestart", () => {
      this.setState({
        isShowList: false,
      });
    });
    this.map.addOverlay(label);
  }
  // 获取小区房源数据
  async getHousesList(id) {
    try {
      Toast.loading("数据加载中", 0, null, false);
      const res = await API.get(`/houses?cityId=${id}`);
      Toast.hide();
      this.setState({
        housesList: res.data.body.list,
        // 展示房源列表
        isShowList: true,
      });
    } catch (e) {
      Toast.hide();
    }
  }

  // 封装渲染房屋列表的方法
  renderHousesList() {
    return this.state.housesList.map((item) => (
      <HouseItem
        key={item.houseCode}
        src={BASE_URL + item.houseImg}
        title={item.title}
        desc={item.desc}
        tags={item.tags}
        price={item.price}
        onClick={() => this.props.history.push(`/detail/${item.houseCode}`)}
      />
    ));
  }

  render() {
    return (
      <div className={styles.map}>
        {/* 顶部导航栏组件 */}
        <NavHeader>地图找房</NavHeader>
        {/* 地图容器元素 */}
        <div id="container" className={styles.container} />

        {/* 房源列表 */}
        {/* 添加 styles.show 展示房屋列表 */}
        <div
          className={[
            styles.houseList,
            this.state.isShowList ? styles.show : "",
          ].join(" ")}
        >
          <div className={styles.titleWrap}>
            <h1 className={styles.listTitle}>房屋列表</h1>
            <Link className={styles.titleMore} to="/home/list">
              更多房源
            </Link>
          </div>

          <div className={styles.houseItems}>
            {/* 房屋结构 */}
            {this.renderHousesList()}
          </div>
        </div>
      </div>
    );
  }
}
